package seatiger.tomcat.coyote.http11.filters;

import seatiger.tomcat.coyote.InputBuffer;
import seatiger.tomcat.coyote.Request;
import seatiger.tomcat.coyote.http11.InputFilter;
import seatiger.tomcat.util.buf.ByteChunk;

import java.io.IOException;

/**
 * 如果报文头部有content-length 并且长度大于0，这个过滤器会通过底层流读取指定的长度
 */
public class IdentityInputFilter implements InputFilter {

    /**
     * 报文头 内容长度
     */
    protected int contentLength = -1;

    /**
     * 剩余的字节
     */
    protected long remaining = 0;

    /**
     * 下一个执行的buffer
     */
    protected InputBuffer inputBuffer;

    /**
     * 读取剩余的字节
     */
    protected ByteChunk endChunk = new ByteChunk();

    @Override
    public int doRead(ByteChunk chunk, Request request) throws IOException {
        int result = -1;
        if (contentLength >= 0) {
            if (remaining > 0) {
                int nRead = inputBuffer.doRead(chunk,request);
                if (nRead > remaining) {
                    chunk.setBytes(chunk.getBuff(),chunk.getStart(), (int) remaining);
                    result = (int) remaining;
                }else {
                    result = nRead;
                }
                remaining = remaining - nRead;
            }else {
                chunk.recycle();
                result = -1;
            }
        }
        return result;
    }

    @Override
    public void setRequest(Request request) {
        contentLength = request.getContentLength();
        remaining = contentLength;
    }

    @Override
    public void recycle() {
        contentLength = -1;
        remaining = 0;
        endChunk.recycle();
    }

    @Override
    public void setBuffer(InputBuffer inputBuffer) {
        this.inputBuffer = inputBuffer;
    }

    /**
     * 将底层流中剩余的数据全部读出
     * @return
     * @throws IOException
     */
    @Override
    public long end() throws IOException {
        while (remaining > 0){
            int nRead = inputBuffer.doRead(endChunk,null);
            if (nRead > 0) {
                remaining = remaining = nRead;
            }else {
                remaining = 0;
            }
        }
        return -remaining;
    }
}
